package com.lsyw.intergrate.controller.websocket;


import com.lsyw.intergrate.config.WebSocketConfig;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;


@Component
@ServerEndpoint(value = "/websocket/{sid}", configurator = WebSocketConfig.class)
public class WebSocketController {


    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;

    /**
     * concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
     */
    private static CopyOnWriteArraySet<WebSocketController> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 接收sid
     */
    private String sid = "";

    /**
     * 功能描述: <br>
     * 〈连接建立成功调用的方法〉
     *
     * @Param: [session, sid]
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/3 15:06
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        this.session = session;
        //加入set中
        webSocketSet.add(this);
        //在线数加1
        addOnlineCount();
        System.out.println("有新窗口开始监听：" + sid + "有新连接加入！当前在线人数为" + getOnlineCount());
        this.sid = sid;

        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            System.out.println("websocket IO异常");
        }
    }

    /**
     * 功能描述: <br>
     * 〈连接关闭调用的方法〉
     *
     * @Param: []
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/3 15:30
     */
    @OnClose
    public void onClose() {
        //从set中删除
        webSocketSet.remove(this);
        //在线数减1
        subOnlineCount();
        System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 功能描述: <br>
     * 〈收到客户端消息后调用的方法,message:客户端发送过来的消息〉
     *
     * @Param: [message 接收到的消息, session ]
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/4 11:29
     */
    @OnMessage
    public void onMessage(String message) {
        System.out.println("来自客户端的消息:" + message);
        //私发消息
        try {
            if (message.equals("1")) {
                this.sendMessage("{\"alarmType\":\"fire\",\"info\":{\"createdTime\":{\"date\":4,\"day\":5,\"hours\":16,\"minutes\":18,\"month\":11,\"seconds\":25,\"time\":1607069905000,\"timezoneOffset\":-480,\"year\":120},\"description\":\"fireDetection\",\"deviceId\":\"0905aa60bb864b95b4dc3a6b4fe00914\",\"id\":\"7BCF7302-4375-2247-943B-2D4444D3DE0E\",\"imageUrl\":\"http://192.20.1.2:6120/pic?0dd100=e2-0ip071o850ed0=--6cz513d194002i9b7*=*d8d2i*s1d=i8p1p=*m7i1t=7e0966500293i0s8*e49b-10o1e0*l22bfd00i80=\",\"isDelete\":0,\"jd\":\"\",\"level\":0,\"maxTemperature\":94,\"srcIndex\":\"dd7996ddba49488ab5cbe3d4a91bf449\",\"status\":0,\"type\":\"192515\",\"unit\":\"celsius\",\"updatedTime\":null,\"visibleUrl\":\"http://192.20.1.2:6120/pic?0dd100=e2-0ip071o470ed2=--6cz513d194002i9b7*=*d8d2i*s1d=i8p1p=*m8i1t=7e0966500493i0s8*e09b-26o1e0*l22bfd00i80=\",\"wd\":[]}}");
            } else if (message.equals("2")) {
                this.sendMessage("{\"alarmType\":\"gps\",\"info\":{\"createdTime\":{\"date\":8,\"day\":2,\"hours\":8,\"minutes\":37,\"month\":11,\"seconds\":15,\"time\":1607387835000,\"timezoneOffset\":-480,\"year\":120},\"deviceId\":\"9466650c57f044dea4fd65cad4194307\",\"hkCode\":\"953f6b658a00479abc83bbf6d303a1b9\",\"id\":\"1456AD17-AEB5-0848-8AEC-C16215F1D469\",\"isDelete\":0,\"jd\":\"43295713\",\"moveEquipmentId\":\"move_equipment_2\",\"updatedTime\":null,\"wd\":\"11329275\"}}");
            } else if (message.equals("zaima?")) {
                this.sendMessage("yes");
                System.out.println("来自服务端的回复:yes");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }


    /**
     * 功能描述: <br>
     * 〈实现服务器主动推送〉
     *
     * @Param: [message]
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/4 15:12
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 功能描述: <br>
     * 〈定点发送消息〉
     *
     * @Param: [message, sid]
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/4 15:12
     */
    public void sendToSpecified(String message, @PathParam("sid") List<String> userList) throws IOException {
        System.out.println("推送消息内容:" + message);
        System.out.println("推送消息对象:" + userList.toString());
        // 定点发送
        List<WebSocketController> list = webSocketSet.stream().filter(r -> userList.contains(r.sid)).collect(Collectors.toList());
        for (WebSocketController item : list) {
            if (item.session.isOpen()) {
                item.session.getBasicRemote().sendText(message);
            }
        }

    }

    /**
     * 功能描述: <br>
     * 〈定点发送消息〉
     *
     * @Param: [message, sid]
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/4 15:12
     */
    public void sendToUserIds(String message, @PathParam("sid") List<String> userList) throws IOException {
        System.out.println("推送消息内容:" + message);
        // 定点发送
        List<WebSocketController> list = webSocketSet.stream().filter(r -> userList.contains(r.sid.split("\\$")[0])).collect(Collectors.toList());
        System.out.println("推送消息对象:" + list.stream().map(r -> r.sid).collect(Collectors.joining(",")));
        for (WebSocketController item : list) {
            if (item.session.isOpen()) {
                item.session.getBasicRemote().sendText(message);
            }
        }
    }

    /**
     * 功能描述: <br>
     * 〈群发自定义消息〉
     *
     * @Param: [message, sid]
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/4 15:12
     */
    public static void sendInfo(String message, @PathParam("sid") String sid) {
        System.out.println("推送消息到窗口" + sid + ",推送消息内容:" + message);
        for (WebSocketController item : webSocketSet) {
            try {
                //设定只能推送这个sid，为null则全部推送
                if (sid == null) {
                    item.sendMessage(message);
                } else if (item.sid.equals(sid)) {
                    List<String> list =new ArrayList<>();
                    list.add(sid);
                    item.sendToSpecified(message,list);
                }
            } catch (IOException e) {
                continue;
            }
        }
    }

    /**
     * 功能描述: <br>
     * 〈群发自定义消息〉
     *
     * @Param: [message, sid]
     * @Return: void
     * @Author: 刘磊
     * @Date: 2020/9/4 15:12
     */
    public static void sendInfoOutLoginUser(String message, @PathParam("sid") String sid) {
        System.out.println("推送消息到窗口" + sid + ",推送消息内容:" + message);
        for (WebSocketController item : webSocketSet) {
            try {
                //设定只能推送这个sid，为null则全部推送
                if (sid == null) {
                    item.sendMessage(message);
                } else if (!item.sid.equals(sid)) {
                    item.sendMessage(message);
                }
            } catch (IOException e) {
                continue;
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketController.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketController.onlineCount--;
    }
}